using System;
using System.Collections.Generic;
using System.Windows.Forms;
using AssetManagementSystem.Model;
using AssetManagementSystem.Presenter;
using AssetManagementSystem.Utils;
using AssetManagementSystem.Utils.Events;
using AssetManagementSystem.View.IView;

namespace AssetManagementSystem.View.Controls {
    public partial class ControlAssets : UserControl, IAssetView, IGroupView {

        Dictionary<string, Asset> assetList;
        Dictionary<string, Group> groupList;
        private const string ALL_GROUPS = "*ALL*";

        //==================================================
        // IAssetView Events
        //==================================================
        public event EventHandler Assets_LoadAll;
        public event EventHandler<SearchEventArgs> Assets_Find;
        public event EventHandler<AssetEventArgs> Asset_Create;
        public event EventHandler<AssetEventArgs> Asset_Update;
        public event EventHandler<AssetEventArgs> Asset_Delete;
        public event EventHandler<AssetPropertiesEventArgs> AssetProperty_Delete;
        //==================================================

        //==================================================
        // IGroupView Events
        //==================================================
        public event EventHandler Groups_LoadAll;
        public event EventHandler<SearchEventArgs> Groups_Find;
        public event EventHandler<GroupEventArgs> Group_Create;
        public event EventHandler<GroupEventArgs> Group_Update;
        public event EventHandler<GroupEventArgs> Group_Delete;
        public event EventHandler<GroupPropertiesEventArgs> GroupProperty_Delete;
        //==================================================

        //==================================================
        // View Constructor
        //==================================================
        public ControlAssets() {
            InitializeComponent();
            assetList = new Dictionary<string, Asset>();
            groupList = new Dictionary<string, Group>();

            //Create a presenter to handle events and update display data
            AssetPresenter assetPresenter = new AssetPresenter(this);
            //Create a group presenter
            GroupPresenter groupPresenter = new GroupPresenter(this);
            //fire event to request a list of all assets
            this.Assets_LoadAll.Invoke(this, new EventArgs());
            //fire event to request a list of all groups
            this.Groups_LoadAll.Invoke(this, new EventArgs());
        }
        //==================================================

        //==================================================
        // IAssetView Methods
        //==================================================
        public void SetAssetList(List<Asset> assets) {
            this.assetList.Clear();
            foreach (Asset asset in assets) {
                this.assetList.Add(asset.Id, asset);
            }
            RefreshAssetDisplay();
        }
        //==================================================

        //==================================================
        // IGroupView Methods
        //==================================================
        public void SetGroupList(List<Group> groups) {
            this.groupList.Clear();
            foreach (Group group in groups) {
                this.groupList.Add(group.Name, group);
            }
            RefreshGroupDisplay();
        }
        //==================================================

        //==================================================
        // Shared Interface Methods
        //==================================================
        public void ShowMessage(string message) {
            MessageBox.Show(message);
        }
        //==================================================

        private void ControlAssets_Load(object sender, EventArgs e) {
            
        }

        public void RefreshAll() {
            //fire event to request a list of all assets
            this.Assets_LoadAll.Invoke(this, new EventArgs());
            //fire event to request a list of all groups
            this.Groups_LoadAll.Invoke(this, new EventArgs());
        }

        //=============== SETTING THE DATA FOR THE ASSETS TAB ====================================================
        //Setting Groups
        public void RefreshGroupDisplay() {
            gridGroups.Rows.Clear();
            gridGroups.Rows.Add(Group.ALL, Group.ALL);
            foreach (KeyValuePair<string, Group> group in this.groupList) {
                gridGroups.Rows.Add(group.Value.Name, group.Value.Description);
            }
        }

        //display assets
        public void RefreshAssetDisplay() {
            //get the group to display - default all groups.
            string groupName = Group.ALL;
            if (gridGroups.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                groupName = gridGroups.SelectedRows[0].Cells["GroupName"].Value.ToString();
            }
            //display assets from the selected group
            gridAssets.Rows.Clear();
            foreach (KeyValuePair<string, Asset> asset in assetList) {
                if (groupName == Group.ALL || asset.Value.GroupName == groupName) {
                    gridAssets.Rows.Add(asset.Key, asset.Value.Name, asset.Value.GroupName, asset.Value.Description);
                }
            }
        }
        //=========================================================================================================


        public void AddAsset_Click(object sender, EventArgs e) {
            UIAssetEditor assetEdit = new UIAssetEditor(groupList);
            assetEdit.Save_Clicked += new EventHandler<AssetEventArgs>(AssetCreate);
            assetEdit.Show();
        }

        private void gridAsset_Assets_SelectionChanged(object sender, EventArgs e) {
            //set the properties grid to display the properties of the selected asset.
            gridAsset_AssetProperties.Rows.Clear();
            if (gridAssets.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                Asset asset = assetList[gridAssets.SelectedRows[0].Cells["AssetId"].Value.ToString()];
                foreach (KeyValuePair<string, string> property in asset.Properties) {
                    gridAsset_AssetProperties.Rows.Add(property.Key, property.Value);
                }
            }
        }

        private void gridAsset_Groups_SelectionChanged(object sender, EventArgs e) {
            RefreshAssetDisplay();
        }

        private void btnAsset_EditAsset_Click(object sender, EventArgs e) {
            string assetId = "";

            if (gridAssets.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                assetId = gridAssets.SelectedRows[0].Cells["AssetId"].Value.ToString();
            }
            Asset asset = assetList[assetId];
            UIAssetEditor assetEdit = new UIAssetEditor(groupList, asset);
            assetEdit.Save_Clicked += new EventHandler<AssetEventArgs>(AssetUpdate);
            assetEdit.Delete_Properties += new EventHandler<AssetPropertiesEventArgs>(AssetPropertiesDelete);
            assetEdit.FormClosed += new FormClosedEventHandler(AssetEditorClosed);
            assetEdit.Show();
        }

        private void AssetEditorClosed(object sender, EventArgs e) {
            this.btnAsset_FindAssets_Click(sender, e);
        }

        private void AssetCreate(object sender, AssetEventArgs e) {
            this.Asset_Create.Invoke(sender, e);
        }

        private void AssetUpdate(object sender, AssetEventArgs e) {
            this.Asset_Update.Invoke(sender, e);
        }

        private void AssetDelete(object sender, AssetEventArgs e) {
            this.Asset_Delete.Invoke(sender, e);
        }

        private void AssetPropertiesDelete(object sender, AssetPropertiesEventArgs e) {
            this.AssetProperty_Delete.Invoke(sender, e);
        }

        private void btnAsset_FindGroups_Click(object sender, EventArgs e) {
            this.Groups_Find.Invoke(sender, new SearchEventArgs(txtAsset_FindGroups.Text, "Group"));
        }

        private void btnAsset_FindAssets_Click(object sender, EventArgs e) {
            this.Assets_Find.Invoke(sender, new SearchEventArgs(txtAsset_FindAssets.Text, "Asset"));
        }

        private void btnAsset_AddGroup_Click(object sender, EventArgs e) {
            UIGroupEditor groupEdit = new UIGroupEditor();
            groupEdit.Save_Clicked += new EventHandler(Group_Saved);
            groupEdit.Show();
        }

        private void Group_Saved(object sender, EventArgs args) {
            //Get the real arguments and the sender ui.
            Dictionary<string, string> realArgs = ((DictionaryEventArgs)args).Args;
            UIGroupEditor propSender = (UIGroupEditor)sender;

            //Make sure property doesn't already exist.
            if (groupList.ContainsKey(realArgs[UIPropertyEditor.NAME])) {
                //it already exists, so cannot be added.
                MessageBox.Show("A property with that name already exists, another cannot be added.");
            } else {
                //it didn't exist, so add it and get rid of the property editor window.
                this.Group_Create(this, new GroupEventArgs(new Group(realArgs[UIGroupEditor.NAME], realArgs[UIGroupEditor.DESCRIPTION], new List<string>())));
                propSender.Close();
                RefreshGroupDisplay();
            }

        }

        private void btnAsset_DeleteGroup_Click(object sender, EventArgs e) {
            //string groupName = Group.ALL;
            if (gridGroups.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                string groupName = gridGroups.SelectedRows[0].Cells["GroupName"].Value.ToString();

                //The 'ALL' group can't be deleted, since it's not a real group
                if (groupName == Group.ALL) {
                    MessageBox.Show("The 'ALL' group cannot be deleted.");
                    return;
                }
                
                //make sure the group being deleted has no assets
                foreach (KeyValuePair<string, Asset> asset in assetList) {
                    if (asset.Value.GroupName == groupName) {
                        MessageBox.Show("The group still contains assets, these must be assigned to another group or deleted before the group can be deleted.");
                        return;
                    }
                }

                DialogResult dialogResult = MessageBox.Show("Are you sure you want to delete this Group? The operation cannot be undone.", 
                    "Delete Group", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (dialogResult == DialogResult.Yes) {
                    //if the method gets to here the group is deletable.
                    Group_Delete.Invoke(this, new GroupEventArgs(groupList[groupName]));
                    RefreshAll();
                }
            }
        }

        private void btnAsset_DeleteAsset_Click(object sender, EventArgs e) {
            if (gridAssets.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                DialogResult dialogResult = MessageBox.Show("Are you sure you want to delete this Asset? The operation cannot be undone.", 
                    "Delete Asset", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (dialogResult == DialogResult.Yes) {
                    Asset asset = assetList[gridAssets.SelectedRows[0].Cells["AssetId"].Value.ToString()];
                    Asset_Delete(this, new AssetEventArgs(asset));
                }
            }
        }
    }
}
